#include <unistd.h>
#include <float.h>
#include "plugin.h"
#include "commtraff.h"
#include "commtraff_socket_server.h"
#include "commtraff_message_handler.h"
#include "sqlite3_utils.h"

#include "commtraff_info_print.h"
#include "common.h"

static void HandleMessage(AsyncMessage *msg);

static AsyncHandler g_handler = {"commtraff", NULL};

static const char *config_keys[] = {IS_PRINT_KEY};

static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);

typedef struct {
    bool isPrintCommTraff;
} CommTraffConfig;

static  CommTraffConfig g_config = {
        .isPrintCommTraff = false ,
};

static CommTraffCommand *g_queryCommand = NULL;

data_source_t g_rpcDataSources[] = {
        {.name = "proxyHandle", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "stubHandle", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "sendDataLen", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "recvDataLen", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "recvDataSeq", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "sendDataSeq", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "time", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
};
static data_set_t g_rpcTraffDS = {
    .ds = g_rpcDataSources,
    .ds_num = sizeof(g_rpcDataSources)/sizeof(data_source_t),
    .type = RPC_DS_NAME
};

data_source_t g_transportDataSources[] = {
        {.name = "pid", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "time", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "sockId", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "protocol", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "sendBytes", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "sendPacks", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "recvBytes", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "recvPacks", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
};

static data_set_t g_transportTraffDS = {
        .ds = g_transportDataSources,
        .ds_num = sizeof(g_transportDataSources)/sizeof(data_source_t),
        .type = TRANSPORT_DS_NAME
};

data_source_t g_sessionDataSources[] = {
        {.name = "pid", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "time", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "handle", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "channelId", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "connId", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "sessionId", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "sessionType", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "sendBytes", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
        {.name = "recvBytes", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
};

static data_set_t g_sessionTraffDS = {
        .ds = g_sessionDataSources,
        .ds_num = sizeof(g_sessionDataSources)/sizeof(data_source_t),
        .type = SESSION_DS_NAME
};

data_source_t g_wpaDataSources[] = {
        {.name = "signal", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX},
        {.name = "noise", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX},
        {.name = "snr", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX},
        {.name = "txrate", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX},
        {.name = "rxrate", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX},
        {.name = "realTxrate", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX},
        {.name = "realRxrate", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX},
        {.name = "txEfficiency", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX},
        {.name = "frequency", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX},
        {.name = "txPackets", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX},
        {.name = "rxPackets", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX},
        {.name = "chload", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX},
        {.name = "txBytes", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX},
        {.name = "rxBytes", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX},
        {.name = "txFailed", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX},
        {.name = "txRetries", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX},
        {.name = "time", .type = DS_TYPE_GAUGE, .min = DBL_MIN, .max = DBL_MAX,},
};

static data_set_t g_wpaTraffDS = {
        .ds = g_wpaDataSources,
        .ds_num = sizeof(g_wpaDataSources) / sizeof(data_source_t),
        .type = WPA_DS_NAME
};

void CustomFreeMessage(AsyncMessage *msg)
{
    if (msg == NULL) {
        return;
    }
    if (msg->obj != NULL) {
        free(msg->obj);
        msg->obj = NULL;
    }
    free(msg);
}

void OnSocketSeverRecv(char *buffer, int length)
{
    if (length != sizeof(CommTraffCommand)) {
        ERROR("OnSocketSeverRecv: invalid length %d, expected %zu", length, sizeof(CommTraffCommand));
        return;
    }
    
    if (g_handler.looper == NULL) {
        ERROR("OnSocketSeverRecv: g_handler.looper is NULL");
        return;
    }
    
    AsyncMessage *msg = MallocAsyncMessage();
    if (msg == NULL) {
        ERROR("OnSocketSeverRecv: MallocAsyncMessage failed");
        return;
    }

    // 创建CommTraffCommand节点
    CommTraffCommand *node = (CommTraffCommand *)calloc(1, sizeof(CommTraffCommand));
    if (node == NULL) {
        ERROR("OnSocketSeverRecv: calloc failed for CommTraffCommand");
        FreeAsyncMessage(msg);
        return;
    }

    // 拷贝数据
    memcpy(node, buffer, sizeof(CommTraffCommand));
    msg->obj = node;
    msg->handler = &g_handler;
    msg->HandleMessage = HandleMessage;
    msg->FreeMessage = CustomFreeMessage;

    // 投递消息，如果失败需要清理资源
    if (g_handler.looper->PostMessage == NULL) {
        ERROR("OnSocketSeverRecv: PostMessage function is NULL");
        free(node);
        FreeAsyncMessage(msg);
        return;
    }
    
    g_handler.looper->PostMessage(g_handler.looper, msg);
}

void SessionTraffHandle(SessionTraff *sessionTraff)
{
    value_list_t vl = VALUE_LIST_INIT;
    memset(&vl, 0, sizeof(vl));
    value_t values[] = {
        { .gauge = sessionTraff->pid },
        { .gauge = sessionTraff->time },
        { .gauge = sessionTraff->handle },
        { .gauge = sessionTraff->channelId },
        { .gauge = sessionTraff->connId },
        { .gauge = sessionTraff->sessionId },
        { .gauge = sessionTraff->sessionType },
        { .gauge = sessionTraff->sendBytes },
        { .gauge = sessionTraff->recvBytes },
    };
    vl.values = values;
    vl.values_len = sizeof(values) / sizeof(value_t);

    // 把字符串数据添加到meta数据中
    vl.meta = meta_data_create();
    if (vl.meta == NULL) {
        ERROR("SessionTraffHandle: meta_data_create failed");
        return;
    }
    // 确保字符串以 \0 结尾
    sessionTraff->localSessionName[SESSION_NAME_LEN - 1] = '\0';
    sessionTraff->peerSessionName[SESSION_NAME_LEN - 1] = '\0';
    sessionTraff->peerUdidHash[COMMTRAFF_UDID_HASH_LEN - 1] = '\0';
    meta_data_add_string(vl.meta, "localSessionName", (char *)sessionTraff->localSessionName);
    meta_data_add_string(vl.meta, "peerSessionName", (char *)sessionTraff->peerSessionName);
    meta_data_add_string(vl.meta, "peerUdidHash", (char *)sessionTraff->peerUdidHash);
    vl.interval = DOUBLE_TO_CDTIME_T(1);
    sstrncpy(vl.plugin, PLUGIN_NAME, sizeof(vl.plugin));
    sstrncpy(vl.type, SESSION_DS_NAME, sizeof(vl.type));
    snprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%s-%s", (char *)sessionTraff->localSessionName, (char *)sessionTraff->peerSessionName, (char *)sessionTraff->peerUdidHash);
    plugin_dispatch_values(&vl);

    meta_data_destroy(vl.meta);
}

void TransportTraffHandle(TransportTraff *transportTraff)
{
    value_list_t vl = VALUE_LIST_INIT;
    memset(&vl, 0, sizeof(vl));
    value_t values[] = {
            { .gauge = transportTraff->pid },
            { .gauge = transportTraff->time },
            { .gauge = transportTraff->sockId },
            { .gauge = transportTraff->protocol },
            { .gauge = transportTraff->sendBytes },
            { .gauge = transportTraff->sendPacks },
            { .gauge = transportTraff->recvBytes },
            { .gauge = transportTraff->recvPacks },
    };
    vl.values = values;
    vl.values_len = sizeof(values) / sizeof(value_t);

    // 把字符串数据添加到meta数据中
    vl.meta = meta_data_create();
    if (vl.meta == NULL) {
        ERROR("TransportTraffHandle: meta_data_create failed");
        return;
    }
    // 确保字符串以 \0 结尾
    transportTraff->ifName[IF_NAMESIZE - 1] = '\0';
    transportTraff->local[INET6_ADDRSTRLEN - 1] = '\0';
    transportTraff->remote[INET6_ADDRSTRLEN - 1] = '\0';
    meta_data_add_string(vl.meta, "ifName", (char *)transportTraff->ifName);
    meta_data_add_string(vl.meta, "srcAddr", (char *)transportTraff->local);
    meta_data_add_string(vl.meta, "dstAddr", (char *)transportTraff->remote);

    vl.interval = DOUBLE_TO_CDTIME_T(1);
    sstrncpy(vl.plugin, PLUGIN_NAME, sizeof(vl.plugin));
    sstrncpy(vl.type, TRANSPORT_DS_NAME, sizeof(vl.type));
    snprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%s-%s", transportTraff->ifName, transportTraff->local, transportTraff->remote);
    plugin_dispatch_values(&vl);

    meta_data_destroy(vl.meta);
}

void RpcTraffHandle(RpcTraff *rpcTraff)
{
    value_list_t vl = VALUE_LIST_INIT;
    memset(&vl, 0, sizeof(vl));
    value_t values[] = {
            { .gauge = (gauge_t)rpcTraff->proxyHandle },
            { .gauge = (gauge_t)rpcTraff->stubHandle },
            { .gauge = (gauge_t)rpcTraff->sendDataLen },
            { .gauge = (gauge_t)rpcTraff->recvDataLen },
            { .gauge = (gauge_t)rpcTraff->recvDataSeq },
            { .gauge = (gauge_t)rpcTraff->sendDataSeq },
            { .gauge = (gauge_t)rpcTraff->time },
            { .gauge = (gauge_t)rpcTraff->localpid },
            { .gauge = (gauge_t)rpcTraff->localuid },
            { .gauge = (gauge_t)rpcTraff->peerpid },
            { .gauge = (gauge_t)rpcTraff->peeruid },
    };
    vl.values = values;
    vl.values_len = sizeof(values) / sizeof(value_t);

    vl.interval = DOUBLE_TO_CDTIME_T(1);
    sstrncpy(vl.plugin, PLUGIN_NAME, sizeof(vl.plugin));
    sstrncpy(vl.type, RPC_DS_NAME, sizeof(vl.type));

    plugin_dispatch_values(&vl);

}

void WpaTraffHandle(WpaTraff *wpaTraff)
{
    value_list_t vl = VALUE_LIST_INIT;
    memset(&vl, 0, sizeof(vl));
    value_t values[] = {
            { .gauge = (gauge_t)wpaTraff->signal },
            { .gauge = (gauge_t)wpaTraff->noise },
            { .gauge = (gauge_t)wpaTraff->snr },
            { .gauge = (gauge_t)wpaTraff->txrate },
            { .gauge = (gauge_t)wpaTraff->rxrate },
            { .gauge = (gauge_t)wpaTraff->realTxrate },
            { .gauge = (gauge_t)wpaTraff->realRxrate },
            { .gauge = (gauge_t)wpaTraff->txEfficiency },
            { .gauge = (gauge_t)wpaTraff->frequency },
            { .gauge = (gauge_t)wpaTraff->txPackets },
            { .gauge = (gauge_t)wpaTraff->rxPackets },
            { .gauge = (gauge_t)wpaTraff->chload },
            { .gauge = (gauge_t)wpaTraff->txBytes },
            { .gauge = (gauge_t)wpaTraff->rxBytes },
            { .gauge = (gauge_t)wpaTraff->txFailed },
            { .gauge = (gauge_t)wpaTraff->txRetries },
            { .gauge = (gauge_t)wpaTraff->time },
    };
    vl.values = values;
    vl.values_len = sizeof(values) / sizeof(value_t);
    vl.interval = DOUBLE_TO_CDTIME_T(1);
    sstrncpy(vl.plugin, PLUGIN_NAME, sizeof(vl.plugin));
    sstrncpy(vl.type, WPA_DS_NAME, sizeof(vl.type));
    // 确保字符串以 \0 结尾
    wpaTraff->ifName[IF_NAMESIZE - 1] = '\0';
    snprintf(vl.type_instance, sizeof(vl.type_instance), "%s", wpaTraff->ifName);
    vl.meta = meta_data_create();
    if (vl.meta == NULL) {
        ERROR("WpaTraffHandle: meta_data_create failed");
        return;
    }
    meta_data_add_string(vl.meta, "ifName", (char *)wpaTraff->ifName);
    plugin_dispatch_values(&vl);
    meta_data_destroy(vl.meta);
}

void HisyseventTraffHandle(HisyseventData *hisyseventData)
{
    value_list_t vl = VALUE_LIST_INIT;
    memset(&vl, 0, sizeof(vl));
    value_t values[] = {
            { .gauge = hisyseventData->value },
    };
    vl.values = values;
    vl.values_len = 1;
    vl.interval = DOUBLE_TO_CDTIME_T(1);
    sstrncpy(vl.plugin, HISYSEVENT_DS_NAME, sizeof(vl.plugin));
    sstrncpy(vl.type, "hisyseventTest", sizeof(vl.type));
    vl.meta = meta_data_create();
    if (vl.meta == NULL) {
        ERROR("HisyseventTraffHandle: meta_data_create failed");
        return;
    }
    // 确保字符串以 \0 结尾
    hisyseventData->domain[sizeof(hisyseventData->domain) - 1] = '\0';
    hisyseventData->event[sizeof(hisyseventData->event) - 1] = '\0';
    hisyseventData->field[sizeof(hisyseventData->field) - 1] = '\0';
    meta_data_add_string(vl.meta, "domain", hisyseventData->domain);
    meta_data_add_string(vl.meta, "event", hisyseventData->event);
    char key[10] = {0};
    snprintf(key, sizeof(key), "field%d", 0);
    meta_data_add_string(vl.meta, key, hisyseventData->field);

    plugin_dispatch_values(&vl);
    meta_data_destroy(vl.meta);
}

void LinkTraffHandle(LinkTraff *linkTraff)
{
    if (linkTraff == NULL) {
        ERROR("LinkTraffHandle: linkTraff is NULL");
        return;
    }
    
    value_list_t vl = VALUE_LIST_INIT;
    memset(&vl, 0, sizeof(vl));
    
    value_t values[] = {
        { .derive = (derive_t)linkTraff->rxPackets },
        { .derive = (derive_t)linkTraff->txPackets },
        { .derive = (derive_t)linkTraff->rxBytes },
        { .derive = (derive_t)linkTraff->txBytes },
        { .derive = (derive_t)linkTraff->rxErrPackets },
        { .derive = (derive_t)linkTraff->txErrPackets },
        { .derive = (derive_t)linkTraff->rxDropPackets },
        { .derive = (derive_t)linkTraff->txDropPackets },
    };
    
    vl.values = values;
    vl.values_len = sizeof(values) / sizeof(value_t);
    
    // 把字符串数据添加到meta数据中
    vl.meta = meta_data_create();
    if (vl.meta == NULL) {
        ERROR("LinkTraffHandle: meta_data_create failed");
        return;
    }
    // 确保字符串以 \0 结尾
    linkTraff->ifName[IF_NAMESIZE - 1] = '\0';
    meta_data_add_string(vl.meta, "ifName", (char *)linkTraff->ifName);

    vl.interval = DOUBLE_TO_CDTIME_T(1);
    sstrncpy(vl.plugin, PLUGIN_NAME, sizeof(vl.plugin));
    sstrncpy(vl.type, LINK_DS_NAME, sizeof(vl.type));
    snprintf(vl.type_instance, sizeof(vl.type_instance), "%s", linkTraff->ifName);
    plugin_dispatch_values(&vl);
    meta_data_destroy(vl.meta);
}

static void HandleInsertMsg(void *obj)
{
    if (obj == NULL) {
        ERROR("HandleInsertMsg: obj is NULL");
        return;
    }
    CommTraff *node = (CommTraff *)obj;

    if (g_config.isPrintCommTraff) {
        CommTraffInfoPrint(node);
    }

    // 根据流量类型直接处理数据，不再插入链表
    switch (node->traffType) {
        case RPC_LAYER_DATA:
            RpcTraffHandle(&node->data.rpcTraff);
            break;
        case SESSION_LAYER_DATA:
            SessionTraffHandle(&node->data.sessionTraff);
            break;
        case TRANSPORT_LAYER_DATA:
            TransportTraffHandle(&node->data.transportTraff);
            break;
        case WPA_LAYER_DATA:
            WpaTraffHandle(&node->data.wpaTraff);
            break;
        case LINK_LAYER_DATA:
            LinkTraffHandle(&node->data.linkTraff);
            break;
        case HISYSEVENT_DATA:
            HisyseventTraffHandle(&node->data.hisyseventData);
            break;
        default:
            ERROR("HandleMessage: Unknown traffType=%d", node->traffType);
            break;
    }
}

// 添加处理查询规则消息的函数实现
static void HandleQueryRuleMessage(CommTraffCommand *cmd)
{
    if (cmd == NULL) {
        ERROR("HandleQueryRuleMessage: invalid msg");
        return;
    }

    CommTraffInnerQueryRule *queryRule = (CommTraffInnerQueryRule *)&cmd->data.queryRule;

    INFO("HandleDatabaseQuery: traffType=%d, startTime=%"PRIu64", endTime=%"PRIu64" startRecordIndex=%"PRId64"",
            queryRule->traffType, (uint64_t)queryRule->startTime, (uint64_t)queryRule->endTime, queryRule->startRecordIndex);

    // 执行数据库查询
    DbContext *ctx = NULL;
    int32_t ret = OpenDatabase(&ctx);
    if (ret != COMMTRAFF_SUCCESS || ctx == NULL) {
        ERROR("HandleDatabaseQuery: Failed to open database");
        return;
    }
    memset(g_queryCommand->data.result.records, 0, sizeof(CommTraff) * ONCE_RECORD_NUMS);
    g_queryCommand->data.result.recordNums = 0;
    g_queryCommand->cmdType = COMMTRAFF_CMD_QUERY_RESULT;
    g_queryCommand->cPort = cmd->cPort;
    g_queryCommand->data.result.traffType = queryRule->traffType;
    g_queryCommand->data.result.startTime = queryRule->startTime;
    g_queryCommand->data.result.endTime = queryRule->endTime;

    QueryParam queryParam = {
            .ctx = ctx,
            .traffType = queryRule->traffType,
            .startTime = queryRule->startTime,
            .endTime = queryRule->endTime,
            .startRecordIndex = queryRule->startRecordIndex,
    };
    ret = QueryTraffByTimeRange(&queryParam, &g_queryCommand->data.result);
    CloseDatabase(ctx);
    int32_t dataLen = sizeof(CommTraffCommand) + g_queryCommand->data.result.recordNums * sizeof(CommTraff);
    DEBUG("HandleDatabaseQuery: ret=%d  infoNum=%d dataLen=%d ", ret, g_queryCommand->data.result.recordNums, dataLen);
    if (SendDataToClient(cmd->cPort, (uint8_t *)g_queryCommand, dataLen) != 0) {
        return;
    }
}


void HandleMessage(AsyncMessage *msg)
{
    if (msg == NULL || msg->obj == NULL) {
        ERROR("invalid msg");
        return;
    }
    CommTraffCommand* cmd = (CommTraffCommand *)msg->obj;
    switch (cmd->cmdType) {
        case COMMTRAFF_CMD_INSERT_DATA:
            HandleInsertMsg(&cmd->data.insertData);
            break;
        case COMMTRAFF_CMD_QUERY_DATABASE:
            HandleQueryRuleMessage(cmd);
            break;
        default:
            ERROR("HandleMessage: Unknown cmd=%d", cmd->cmdType);
            break;
    }

}

int CommTraffInit()
{
    INFO("CommTraffInit start");
    // 申请ONCE_RECORD_NUMS个CommTraff结构体的内存
    g_queryCommand = (CommTraffCommand *)calloc(1, sizeof(CommTraffCommand) + ONCE_RECORD_NUMS * sizeof(CommTraff));
    if (g_queryCommand == NULL) {
        ERROR("g_commTraff calloc failed");
        return COMMTRAFF_FAIL;
    }
    g_queryCommand->data.result.records = (CommTraff *)(g_queryCommand + 1);
    g_handler.looper = CreateAsyncLooper(g_handler.name);
    if (g_handler.looper == NULL) {
        ERROR("CreateAsyncLooper failed");
        free(g_queryCommand);
        return COMMTRAFF_FAIL;
    }
    SocketServerCb cb = {
        .OnRecv = OnSocketSeverRecv
    };
    if (SocketServerInit(&cb) != COMMTRAFF_SUCCESS) {
        ERROR("SocketServerInit failed");
        DestroyAsyncLooper(g_handler.looper);
        free(g_queryCommand);
        return COMMTRAFF_FAIL;
    }

    INFO("CommTraffInit success, g_queryCommand malloc size=%zu", sizeof(CommTraffCommand) + ONCE_RECORD_NUMS * sizeof(CommTraff));
    return COMMTRAFF_SUCCESS;
}

int CommTraffShutdown()
{
    INFO("CommTraffShutdown not implemented");
    return COMMTRAFF_SUCCESS;
}

static int CommtraffConfig(const char *key, const char *value)
{
    INFO("CommtraffConfig %s=%s", key, value);
    if (strcasecmp(key, IS_PRINT_KEY) == 0)
        g_config.isPrintCommTraff = IS_TRUE(value);
    else
        return -1;
    return 0;
}

int CommtraffRead()
{
    return COMMTRAFF_SUCCESS;
}

void module_register(void)
{
    plugin_register_data_set(&g_rpcTraffDS);
    plugin_register_data_set(&g_transportTraffDS);
    plugin_register_data_set(&g_sessionTraffDS);
    plugin_register_data_set(&g_wpaTraffDS); // 注册 WpaTraff 数据源

    plugin_register_init(PLUGIN_NAME, CommTraffInit);
    plugin_register_config(PLUGIN_NAME, CommtraffConfig, config_keys, config_keys_num);
    plugin_register_read(PLUGIN_NAME, CommtraffRead);
    plugin_register_shutdown(PLUGIN_NAME, CommTraffShutdown);
    return;
} /* void module_register (void) */

